
package com.hlkj.pay.app.merchant.ext.impl.yeepay.handler;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.io.File;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.PrivateKey;
import java.util.*;
import java.util.stream.Collectors;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSONArray;
import com.hlkj.framework.caches.service.RedisTemplateService;
import com.hlkj.framework.common.pojo.CommonResult;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.pay.app.common.impl.UploadServiceImpl;
import com.hlkj.pay.app.merchant.ext.dto.access.ChannelMerchantAccessContext;
import com.hlkj.pay.app.merchant.ext.impl.wxpay.handler.WxPayCommonParamsHandle;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayConfig;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayDivideDetailResp;
import com.hlkj.pay.app.merchant.ext.impl.yeepay.dto.YeePayProductInfo;
import com.hlkj.pay.common.PayResultCode;
import com.hlkj.pay.dto.merchant.MerchantAccessDto;
import com.hlkj.pay.dto.merchant.MerchantAccessScene;
import com.hlkj.pay.dto.merchant.ProviderChannelFeeConfigList;
import com.hlkj.pay.enums.MerchantEnum;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessCertInfoDO;
import com.hlkj.pay.infrastructure.model.merchant.MerchantAccessInfoDO;
import com.hlkj.pay.infrastructure.model.order.PayOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.infrastructure.model.pay.PayWayDO;
import com.hlkj.pay.infrastructure.model.pay.ProviderChannelConfigDO;
import com.hlkj.pay.service.order.IPayOrderService;
import com.hlkj.pay.util.DateUtils;
import com.hlkj.pay.util.ImageUtils;
import com.yeepay.yop.sdk.auth.credentials.PKICredentialsItem;
import com.yeepay.yop.sdk.auth.credentials.YopPKICredentials;
import com.yeepay.yop.sdk.base.security.cert.parser.YopCertParserFactory;
import com.yeepay.yop.sdk.config.enums.CertStoreType;
import com.yeepay.yop.sdk.config.provider.file.YopCertConfig;
import com.yeepay.yop.sdk.security.CertTypeEnum;
import com.yeepay.yop.sdk.security.cert.YopCertCategory;
import com.yeepay.yop.sdk.service.common.YopClient;
import com.yeepay.yop.sdk.service.common.YopClientBuilder;
import com.yeepay.yop.sdk.service.common.request.YopRequest;
import com.yeepay.yop.sdk.service.common.response.YopResponse;
import com.yeepay.yop.sdk.service.mer.MerClient;
import com.yeepay.yop.sdk.service.mer.MerClientBuilder;
import com.yeepay.yop.sdk.service.mer.model.RegisterSaasMerchantV2ContributeMerchantNetInRespDtoResult;
import com.yeepay.yop.sdk.service.mer.model.RegisterSaasMicroV2ContributeMicroMerchantNetInRespDtoResult;
import com.yeepay.yop.sdk.service.mer.request.RegisterSaasMerchantV2Request;
import com.yeepay.yop.sdk.service.mer.request.RegisterSaasMicroV2Request;
import com.yeepay.yop.sdk.service.mer.response.RegisterSaasMerchantV2Response;
import com.yeepay.yop.sdk.service.mer.response.RegisterSaasMicroV2Response;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 易宝服务商 商户进件参数处理
 * 
 * @author HlpayTeam
 * @date 2024/09/26 12:02
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class YeePayCommonParamsHandle {

    private final UploadServiceImpl uploadService;

    private final RedisTemplateService redisTemplateService;

    private final IPayOrderService payOrderService;

    private final MerClient api = MerClientBuilder.builder().build();

    public String subject(String subject) throws UnsupportedEncodingException {
        return URLEncoder.encode(subject, "GBK");
    }



    public void personAccess(YeePayConfig yeePayConfig, ChannelMerchantAccessContext channelMerchantAccessContext){

        MerchantAccessDto merchantAccessDto = channelMerchantAccessContext.getMerchantAccessDto();
        MerchantAccessInfoDO merchantAccessInfo = merchantAccessDto.getMerchantAccessInfo();
        PayChannelRequestDO payChannelRequestDO = new PayChannelRequestDO();
        channelMerchantAccessContext.setPayChannelRequestDO(payChannelRequestDO);

        RegisterSaasMicroV2Request request = new RegisterSaasMicroV2Request();
        try {

            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            // 入网请求号
            request.setRequestNo(merchantAccessInfo.getRequestId());
            // 入网商户业务角色
            request.setBusinessRole(getBusinessRole(yeePayConfig.getPlatformNo(),merchantAccessDto.getMerchantAccessInfo().getMerchantAccessType()));
            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }

            // 商户主体信息
            Map<String,Object> merchantSubjectInfo = new HashMap<>();
            merchantSubjectInfo.put("signName",merchantAccessDto.getMerchantAccessLegal().getName());
            merchantSubjectInfo.put("shortName",merchantAccessDto.getMerchantAccessBusiness().getShortName());
            request.setMerchantSubjectInfo(JSONUtil.toJsonStr(merchantSubjectInfo));

            // 商户法人信息
            Map<String,Object> merchantCorporationInfo = new HashMap<>();
            merchantCorporationInfo.put("legalName",merchantAccessDto.getMerchantAccessLegal().getName());
            merchantCorporationInfo.put("legalLicenceType",certType(merchantAccessDto.getMerchantAccessLegal().getCertType()));
            merchantCorporationInfo.put("legalLicenceNo",merchantAccessDto.getMerchantAccessLegal().getCertNo());
            merchantCorporationInfo.put("legalLicenceFrontUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessLegal().getCertFrontUrl(),yeePayConfig));
            merchantCorporationInfo.put("legalLicenceBackUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessLegal().getCertBackUrl(),yeePayConfig));
            merchantCorporationInfo.put("mobile",merchantAccessDto.getMerchantAccessLegal().getPhone());
            merchantCorporationInfo.put("startDate",merchantAccessDto.getMerchantAccessLegal().getCertBeginDate());
            if(merchantAccessDto.getMerchantAccessLegal().getCertValidityType() == 1){
                merchantCorporationInfo.put("validityType","LONG_TERM ");
            }else{
                merchantCorporationInfo.put("expired",merchantAccessDto.getMerchantAccessLegal().getCertEndDate());
            }
            merchantCorporationInfo.put("legalAddress",merchantAccessDto.getMerchantAccessLegal().getAddress());
            request.setMerchantCorporationInfo(JSONUtil.toJsonStr(merchantCorporationInfo));

            // 经营地址
            Map<String,Object> businessAddressInfo = new HashMap<>();
            businessAddressInfo.put("province",merchantAccessDto.getMerchantAccessBusiness().getProvinceCode());
            businessAddressInfo.put("city",merchantAccessDto.getMerchantAccessBusiness().getCityCode());
            businessAddressInfo.put("district",merchantAccessDto.getMerchantAccessBusiness().getAreaCode());
            businessAddressInfo.put("address",merchantAccessDto.getMerchantAccessBusiness().getAddress());
            request.setBusinessAddressInfo(JSONUtil.toJsonStr(businessAddressInfo));

            // 结算信息
            Map<String,Object> settlementAccountInfo = new HashMap<>();
            settlementAccountInfo.put("settlementDirection","BANKCARD");
            settlementAccountInfo.put("bankAccountType",getBankAccountType(merchantAccessDto.getMerchantAccessCard().getType()));
            settlementAccountInfo.put("bankCardNo",merchantAccessDto.getMerchantAccessCard().getCardNo());
            settlementAccountInfo.put("cnapsCode",merchantAccessDto.getMerchantAccessCard().getBranchCode());
            settlementAccountInfo.put("bankAccountName",merchantAccessDto.getMerchantAccessCard().getName());
            // 对私
            if(merchantAccessDto.getMerchantAccessCard().getType() != 0){
                // 对私法人
                if(merchantAccessDto.getMerchantAccessCard().getType() == 1){
                    settlementAccountInfo.put("licenceNo",merchantAccessDto.getMerchantAccessLegal().getCertNo());
                }else{
                    settlementAccountInfo.put("licenceNo",merchantAccessDto.getMerchantAccessCard().getCertNo());
                }
                settlementAccountInfo.put("licenceType","ID_CARD");
                settlementAccountInfo.put("bankCardUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessCard().getSettleCardFrontUrl(),yeePayConfig));;
                settlementAccountInfo.put("relation","SHAREHOLDER_OR_EMPLOY");
            }
            request.setAccountInfo(JSONUtil.toJsonStr(settlementAccountInfo));

            // 回调通知
            request.setNotifyUrl(channelMerchantAccessContext.getAsyncReturnUrl());

            // 开通产品信息
            List<YeePayProductInfo> productInfos = getProductInfo(channelMerchantAccessContext);
            if(CollUtil.isNotEmpty(productInfos)){
                request.setProductInfo(JSONUtil.toJsonStr(productInfos));
            }

            // 默认开通分账
            List<String> functionServices = new ArrayList<>();
            functionServices.add("SHARE");
            request.setFunctionService(JSONUtil.toJsonStr(functionServices));
            // 分账资质
            Map<String,Object> functionServiceQualificationInfo = new HashMap<>();
            functionServiceQualificationInfo.put("shareScene","FZ_ALL001");
            request.setFunctionServiceQualificationInfo(JSONUtil.toJsonStr(functionServiceQualificationInfo));

            // 收单场景  开通线下必传
            Map<String,Object> businessScene = new HashMap<>();
            businessScene.put("businessSceneList",CollUtil.newArrayList("STATICQR","POS"));
            businessScene.put("isAppIdConfig","YES");
            businessScene.put("appIdConfigType","YEEPAY");
            businessScene.put("isAppIdConfig",yeePayConfig.getAppId());
            request.setBusinessScene(JSONUtil.toJsonStr(businessScene));

            // 产品资质
            Map<String,Object> productQualificationInfo = new HashMap<>();
            productQualificationInfo.put("mcc",merchantAccessDto.getMerchantAccessBusiness().getWechatMcc());
            productQualificationInfo.put("scenePhotoUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessBusiness().getStoreIndoorUrl(),yeePayConfig));
            productQualificationInfo.put("businessPlacePhotoUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessBusiness().getStoreHeaderUrl(),yeePayConfig));
            request.setProductQualificationInfo(JSONUtil.toJsonStr(productQualificationInfo));

            // 记录请求参数
            payChannelRequestDO.setRequestId(request.getRequestNo());
            payChannelRequestDO.setRequestParams(JsonUtils.toJsonString(request));
            payChannelRequestDO.setRequestUrl("/rest/v2.0/mer/register/saas/micro");
            payChannelRequestDO.setRequestTime(System.currentTimeMillis());

            /**
             * 请求号规则：
             * 1.申请状态：非“申请已驳回”时，不允许用同请求号重复发起；
             * 2.申请状态：为“申请已驳回”时，允许同请求号重新发起，商编不变； 若重新换请求号，商编会变；
             */
            if (StrUtil.isNotEmpty(merchantAccessInfo.getSubMchId()) ) {
                // 驳回状态
                if(merchantAccessInfo.getStatus()==MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE.getCode()){
                    request.setRequestNo(merchantAccessInfo.getRequestId());
                }else{
                    String requestId = IdUtil.getSnowflakeNextIdStr();
                    // 更换请求号
                    request.setRequestNo(requestId);
                    merchantAccessInfo.setRequestId(requestId);
                }
            }

            log.info("易宝个人开户 请求参数 request:{}", JsonUtils.toJsonString(request));
            RegisterSaasMicroV2Response response = api.registerSaasMicroV2(request);
            payChannelRequestDO.setResponse(JsonUtils.toJsonString(response.getResult()));
            log.info("易宝个人开户 返回参数 response:{}", payChannelRequestDO.getResponse());

            RegisterSaasMicroV2ContributeMicroMerchantNetInRespDtoResult result = response.getResult();
            if(result.getReturnCode().equals("NIG00000") && StrUtil.isNotEmpty(result.getApplicationNo())){
                merchantAccessInfo.setApplyNo(result.getApplicationNo());
                if(StrUtil.isNotEmpty(result.getMerchantNo())){
                    merchantAccessInfo.setSubMchId(result.getMerchantNo());
                }
                // 下一步就是查询申请状态
                channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.CHANNEL_APPROVE);
                channelMerchantAccessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.SUBMIT);

            }else{
                channelMerchantAccessContext.setRemark(result.getReturnMsg());
                channelMerchantAccessContext.setProcessStatus(Boolean.FALSE);
                channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("易宝个人开户请求失败,失败信息 message: {}", e.getMessage());
            channelMerchantAccessContext.setRemark("易宝个人开户请求失败,失败信息" + (StringUtils.hasText(e.getMessage()) ? e.getMessage() : " 数据解析异常"));
            channelMerchantAccessContext.setProcessStatus(Boolean.FALSE);
            channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
        }

    }

    public void companyAccess(YeePayConfig yeePayConfig, ChannelMerchantAccessContext channelMerchantAccessContext){

        MerchantAccessDto merchantAccessDto = channelMerchantAccessContext.getMerchantAccessDto();
        MerchantAccessInfoDO merchantAccessInfo = merchantAccessDto.getMerchantAccessInfo();
        PayChannelRequestDO payChannelRequestDO = new PayChannelRequestDO();
        channelMerchantAccessContext.setPayChannelRequestDO(payChannelRequestDO);

        try {
            RegisterSaasMerchantV2Request request = new RegisterSaasMerchantV2Request();
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));
            // 入网请求号
            request.setRequestNo(merchantAccessInfo.getRequestId());
            // 入网商户业务角色
            request.setBusinessRole(getBusinessRole(yeePayConfig.getPlatformNo(),merchantAccessDto.getMerchantAccessInfo().getMerchantAccessType()));
            // 上级商户编号
            if(StrUtil.isEmpty(yeePayConfig.getPlatformNo())){
                request.setParentMerchantNo(yeePayConfig.getMchId());
            }else{
                request.setParentMerchantNo(yeePayConfig.getPlatformNo());
            }
            // 商户主体信息
            Map<String,Object> merchantSubjectInfo = new HashMap<>();
            merchantSubjectInfo.put("signName",merchantAccessDto.getMerchantAccessLicense().getName());
            merchantSubjectInfo.put("shortName",merchantAccessDto.getMerchantAccessBusiness().getShortName());
            merchantSubjectInfo.put("signType",companyType(Integer.valueOf(merchantAccessDto.getMerchantAccessLicense().getCompanyType())));
            merchantSubjectInfo.put("licenceUrl", getUploadMerQualUrl(merchantAccessDto.getMerchantAccessLicense().getLicenseUrl(),yeePayConfig));
            merchantSubjectInfo.put("licenceNo",merchantAccessDto.getMerchantAccessLicense().getLicenseCode());
            merchantSubjectInfo.put("openAccountLicenceUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessCard().getLicenseUrl(),yeePayConfig));

            merchantSubjectInfo.put("enterpriseCreditStart",merchantAccessDto.getMerchantAccessLicense().getLicenseBeginDate());
            if(merchantAccessDto.getMerchantAccessLicense().getLicenseValidityType() == 1){
                merchantSubjectInfo.put("validityType","LONG_TERM");
            }else{
                merchantSubjectInfo.put("enterpriseCreditExpired",merchantAccessDto.getMerchantAccessLicense().getLicenseEndDate());
            }
            request.setMerchantSubjectInfo(JSONUtil.toJsonStr(merchantSubjectInfo));

            // 商户法人信息
            Map<String,Object> merchantCorporationInfo = new HashMap<>();
            merchantCorporationInfo.put("legalName",merchantAccessDto.getMerchantAccessLegal().getName());
            merchantCorporationInfo.put("legalLicenceType",certType(merchantAccessDto.getMerchantAccessLegal().getCertType()));
            merchantCorporationInfo.put("legalLicenceNo",merchantAccessDto.getMerchantAccessLegal().getCertNo());
            merchantCorporationInfo.put("legalLicenceFrontUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessLegal().getCertFrontUrl(),yeePayConfig));
            merchantCorporationInfo.put("legalLicenceBackUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessLegal().getCertBackUrl(),yeePayConfig));
            merchantCorporationInfo.put("mobile",merchantAccessDto.getMerchantAccessLegal().getPhone());
            merchantCorporationInfo.put("startDate",merchantAccessDto.getMerchantAccessLegal().getCertBeginDate());
            if(merchantAccessDto.getMerchantAccessLegal().getCertValidityType() == 1){
                merchantCorporationInfo.put("validityType","LONG_TERM ");
            }else{
                merchantCorporationInfo.put("expired",merchantAccessDto.getMerchantAccessLegal().getCertEndDate());
            }
            merchantCorporationInfo.put("legalAddress",merchantAccessDto.getMerchantAccessLegal().getAddress());
            request.setMerchantCorporationInfo(JSONUtil.toJsonStr(merchantCorporationInfo));

            // 商户联系人信息
            Map<String,Object> merchantContactInfo = new HashMap<>();
            // 联系人非同法
            if(merchantAccessDto.getMerchantAccessInfo().getContactType() != null && merchantAccessDto.getMerchantAccessInfo().getContactType() == 0){
                merchantContactInfo.put("contactName",merchantAccessDto.getMerchantAccessLegal().getName());
                merchantContactInfo.put("contactLicenceNo",merchantAccessDto.getMerchantAccessLegal().getCertNo());
                merchantContactInfo.put("contactMobile",merchantAccessDto.getMerchantAccessLegal().getPhone());
                merchantContactInfo.put("contactEmail",merchantAccessDto.getMerchantAccessLegal().getOtherValue());
            }else{
                merchantContactInfo.put("contactName",merchantAccessDto.getMerchantAccessContact().getName());
                merchantContactInfo.put("contactLicenceNo",merchantAccessDto.getMerchantAccessContact().getCertNo());
                merchantContactInfo.put("contactMobile",merchantAccessDto.getMerchantAccessContact().getPhone());
                merchantContactInfo.put("contactEmail",merchantAccessDto.getMerchantAccessContact().getOtherValue());
            }
            request.setMerchantContactInfo(JSONUtil.toJsonStr(merchantContactInfo));

            // 经营地址
            Map<String,Object> businessAddressInfo = new HashMap<>();
            businessAddressInfo.put("province",merchantAccessDto.getMerchantAccessBusiness().getProvinceCode());
            businessAddressInfo.put("city",merchantAccessDto.getMerchantAccessBusiness().getCityCode());
            businessAddressInfo.put("district",merchantAccessDto.getMerchantAccessBusiness().getAreaCode());
            businessAddressInfo.put("address",merchantAccessDto.getMerchantAccessBusiness().getAddress());
            request.setBusinessAddressInfo(JSONUtil.toJsonStr(businessAddressInfo));

            // 结算信息
            Map<String,Object> settlementAccountInfo = new HashMap<>();
            settlementAccountInfo.put("settlementDirection","BANKCARD");
            settlementAccountInfo.put("bankAccountType",getBankAccountType(merchantAccessDto.getMerchantAccessCard().getType()));
            settlementAccountInfo.put("bankCardNo",merchantAccessDto.getMerchantAccessCard().getCardNo());
            settlementAccountInfo.put("cnapsCode",merchantAccessDto.getMerchantAccessCard().getBranchCode());
            settlementAccountInfo.put("bankAccountName",merchantAccessDto.getMerchantAccessCard().getName());
            // 对私
            if(merchantAccessDto.getMerchantAccessCard().getType() != 0){
                // 对私法人
                if(merchantAccessDto.getMerchantAccessCard().getType() == 1){
                    settlementAccountInfo.put("licenceNo",merchantAccessDto.getMerchantAccessLegal().getCertNo());
                }else{
                    settlementAccountInfo.put("licenceNo",merchantAccessDto.getMerchantAccessCard().getCertNo());
                }
                settlementAccountInfo.put("licenceType","ID_CARD");
                settlementAccountInfo.put("bankCardUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessCard().getSettleCardFrontUrl(),yeePayConfig));;
                settlementAccountInfo.put("relation","SHAREHOLDER_OR_EMPLOY");
            }
            request.setSettlementAccountInfo(JSONUtil.toJsonStr(settlementAccountInfo));

            // 受益人信息
            if(CollUtil.isNotEmpty(merchantAccessDto.getMerchantAccessBenefitList())){
                JSONArray uboArray = getUnoArray(merchantAccessDto.getMerchantAccessBenefitList(),yeePayConfig);
                request.setUboInfoList(JSONUtil.toJsonStr(uboArray));
            }

            // 经营类目
            Map<String,Object> industryCategoryInfo = new HashMap<>();
            String mcc = merchantAccessDto.getMerchantAccessBusiness().getMcc();
            if(StrUtil.isNotEmpty(mcc)){
                industryCategoryInfo.put("primaryIndustryCategory",mcc.substring(0,3));
                industryCategoryInfo.put("secondaryIndustryCategory",mcc);
                request.setIndustryCategoryInfo(JSONUtil.toJsonStr(industryCategoryInfo));
            }

            // 开通产品信息
            List<YeePayProductInfo> productInfos = getProductInfo(channelMerchantAccessContext);
            if(CollUtil.isNotEmpty(productInfos)){
                request.setProductInfo(JSONUtil.toJsonStr(productInfos));
                request.setBusinessNotifyUrl(channelMerchantAccessContext.getAsyncReturnUrl());
            }

            // 默认开通分账
            List<String> functionServices = new ArrayList<>();
            functionServices.add("SHARE");
            request.setFunctionService(JSONUtil.toJsonStr(functionServices));
            // 分账资质
            Map<String,Object> functionServiceQualificationInfo = new HashMap<>();
            functionServiceQualificationInfo.put("shareScene","FZ_ALL001");
            request.setFunctionServiceQualificationInfo(JSONUtil.toJsonStr(functionServiceQualificationInfo));

            // 首单场景  开通线下必传
            Map<String,Object> businessScene = new HashMap<>();
            businessScene.put("businessSceneList",CollUtil.newArrayList("STATICQR","POS"));
            businessScene.put("isAppIdConfig","YES");
            businessScene.put("appIdConfigType","YEEPAY");
            businessScene.put("isAppIdConfig",yeePayConfig.getAppId());
            request.setBusinessScene(JSONUtil.toJsonStr(businessScene));


            // 产品资质
            Map<String,Object> productQualificationInfo = new HashMap<>();
            productQualificationInfo.put("mcc",merchantAccessDto.getMerchantAccessBusiness().getWechatMcc());
            productQualificationInfo.put("scenePhotoUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessBusiness().getStoreIndoorUrl(),yeePayConfig));
            productQualificationInfo.put("businessPlacePhotoUrl",getUploadMerQualUrl(merchantAccessDto.getMerchantAccessBusiness().getStoreHeaderUrl(),yeePayConfig));
            request.setProductQualificationInfo(JSONUtil.toJsonStr(productQualificationInfo));

            // 回调通知
            request.setNotifyUrl(channelMerchantAccessContext.getAsyncReturnUrl());
            // 记录请求参数
            payChannelRequestDO.setRequestId(request.getRequestNo());
            payChannelRequestDO.setRequestParams(JsonUtils.toJsonString(request));
            payChannelRequestDO.setRequestUrl("/rest/v2.0/mer/register/saas/merchant");
            payChannelRequestDO.setRequestTime(System.currentTimeMillis());

            /**
             * 请求号规则：
             * 1.申请状态：非“申请已驳回”时，不允许用同请求号重复发起；
             * 2.申请状态：为“申请已驳回”时，允许同请求号重新发起，商编不变； 若重新换请求号，商编会变；
             */
            if (StrUtil.isNotEmpty(merchantAccessInfo.getSubMchId()) ) {
                // 驳回状态
               if(merchantAccessInfo.getStatus()==MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE.getCode()){
                   request.setRequestNo(merchantAccessInfo.getRequestId());
               }else{
                   String requestId = IdUtil.getSnowflakeNextIdStr();
                   // 更换请求号
                   request.setRequestNo(requestId);
                   merchantAccessInfo.setRequestId(requestId);
               }
            }

            log.info("易宝企业开户 请求参数 request:{}", JsonUtils.toJsonString(request));
            RegisterSaasMerchantV2Response response = api.registerSaasMerchantV2(request);

            payChannelRequestDO.setResponse(JsonUtils.toJsonString(response.getResult()));
            log.info("易宝企业开户 返回参数 response:{}", payChannelRequestDO.getResponse());

            RegisterSaasMerchantV2ContributeMerchantNetInRespDtoResult result = response.getResult();
            if(result.getReturnCode().equals("NIG00000") && StrUtil.isNotEmpty(result.getApplicationNo())){
                merchantAccessInfo.setApplyNo(result.getApplicationNo());
                if(StrUtil.isNotEmpty(result.getMerchantNo())){
                    merchantAccessInfo.setSubMchId(result.getMerchantNo());
                }
                // 下一步就是查询申请状态
                channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.CHANNEL_APPROVE);
                channelMerchantAccessContext.setAuditStatus(MerchantEnum.CHANNEL_CONFIG_STATUS.SUBMIT);
            }else{
                channelMerchantAccessContext.setRemark(result.getReturnMsg());
                channelMerchantAccessContext.setProcessStatus(Boolean.FALSE);
                channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
            }


        } catch (Exception e) {
            e.printStackTrace();
            log.error("易宝企业开户请求失败,失败信息 message: {}", e.getMessage());
            channelMerchantAccessContext.setRemark("易宝企业开户请求失败,失败信息" + (StringUtils.hasText(e.getMessage()) ? e.getMessage() : " 数据解析异常"));
            channelMerchantAccessContext.setProcessStatus(Boolean.FALSE);
            channelMerchantAccessContext.setAccessStatus(MerchantEnum.ACCESS_STATUS.APPROVE_REFUSE);
        }

    }


    /**
     * 开通产品参数组装
     * @param channelMerchantBusinessContext
     * @return
     */
    public List<YeePayProductInfo> getProductInfo(ChannelMerchantAccessContext channelMerchantBusinessContext){

        List<YeePayProductInfo> productInfos = new ArrayList<>();
        List<ProviderChannelFeeConfigList> settlementInfos = new ArrayList<>();
        YeePayProductInfo payProductInfo = null;

        // 获取商户费率
        List<ProviderChannelFeeConfigList> merchantFeeConfigList = channelMerchantBusinessContext.getMerchantFeeConfigList();
        // 支付类型分组
        Map<Integer, List<ProviderChannelFeeConfigList>> merchantFeeConfigMap = merchantFeeConfigList.stream()
                .collect(Collectors.groupingBy(merchantFeeConfig -> merchantFeeConfig.getPayWayDO().getType()));
        for (Map.Entry<Integer, List<ProviderChannelFeeConfigList>> entry : merchantFeeConfigMap.entrySet()) {
            switch (PayEnums.PAY_TYPE.fromByCode(entry.getKey())) {
                case WECHAT:
                    // 微信配置对象
                    for(ProviderChannelFeeConfigList feeConfig:entry.getValue()){
                        payProductInfo = new YeePayProductInfo();
                        String productCode = getWxProductCode(feeConfig.getPayWayDO());
                        if(StrUtil.isEmpty(productCode)){
                            continue;
                        }
                        payProductInfo.setProductCode(productCode);

                        setRateType(feeConfig,payProductInfo);
                        productInfos.add(payProductInfo);
                    }
                    break;
                case ALIPAY:
                    for(ProviderChannelFeeConfigList feeConfig:entry.getValue()){
                        payProductInfo = new YeePayProductInfo();
                        String productCode = getAliProductCode(feeConfig.getPayWayDO());
                        if(StrUtil.isEmpty(productCode)){
                            continue;
                        }
                        payProductInfo.setProductCode(productCode);
                        setRateType(feeConfig,payProductInfo);
                        productInfos.add(payProductInfo);
                    }
                    break;
                case UNION_APY:
                    // 银联现在只有 NATIVE
                    // for(ProviderChannelFeeConfigList feeConfig:entry.getValue()){
                    //     payProductInfo = new YeePayProductInfo();
                    //     payProductInfo.setProductCode("USER_SCAN_UNIONPAY_DEBIT");
                    //     setRateType(feeConfig,payProductInfo);
                    //     productInfos.add(payProductInfo);
                    // }
                    break;
                case FUNCTION:
                    for(ProviderChannelFeeConfigList feeConfig:entry.getValue()){
                        if(feeConfig.getStatus() == 1){
                            settlementInfos.add(feeConfig);
                        }
                    }
                    break;
            }

            // 结算费率
            if(CollUtil.isNotEmpty(settlementInfos)){
                // 是否已开通手动结算方式
                boolean MANUAL = false;
                Optional<ProviderChannelFeeConfigList> feeConfig_MANUAL = settlementInfos.stream().filter(conf -> Objects.equals(conf.getPayWayDO().getCode(),MerchantEnum.SETTLE_CYCLE.MANUAL.getPayWayCode())).findFirst();
                if(feeConfig_MANUAL.isPresent()){
                    MANUAL = true;
                }
                // 过滤D1 只能选一种,按优先顺序取
                Optional<ProviderChannelFeeConfigList> feeConfig_OTHER = settlementInfos.stream().filter(conf -> Objects.equals(conf.getPayWayDO().getCode(),MerchantEnum.SETTLE_CYCLE.D0.getPayWayCode())).findFirst();
                // D0
                if(feeConfig_OTHER.isPresent()){
                    payProductInfo = new YeePayProductInfo();
                    payProductInfo.setProductCode("D0");
                    setRateType(feeConfig_OTHER.get(),payProductInfo);
                    productInfos.add(payProductInfo);
                }else{
                    // D1 默认固定值 0
                    feeConfig_OTHER = settlementInfos.stream().filter(conf -> Objects.equals(conf.getPayWayDO().getCode(),MerchantEnum.SETTLE_CYCLE.D1.getPayWayCode())).findFirst();
                    if(feeConfig_OTHER.isPresent()){
                        payProductInfo = new YeePayProductInfo();
                        if(MANUAL){
                            payProductInfo.setProductCode("D1_MANUAL");
                        }else{
                            payProductInfo.setProductCode("D1");
                        }
                        setRateType(feeConfig_OTHER.get(),payProductInfo);
                        productInfos.add(payProductInfo);
                    }else{
                        // T1
                        feeConfig_OTHER = settlementInfos.stream().filter(conf -> Objects.equals(conf.getPayWayDO().getCode(),MerchantEnum.SETTLE_CYCLE.T1.getPayWayCode())).findFirst();
                        if(feeConfig_OTHER.isPresent()){
                            payProductInfo = new YeePayProductInfo();
                            if(MANUAL){
                                payProductInfo.setProductCode("T1_MANUAL");
                            }else{
                                payProductInfo.setProductCode("T1");
                            }
                            setRateType(feeConfig_OTHER.get(),payProductInfo);
                            productInfos.add(payProductInfo);
                        }
                    }
                }
            }
        }
        return productInfos;
    }

    /**
     * 更新费率信息
     * @param feeConfig
     * @param productInfo
     */
    public void setRateType(ProviderChannelFeeConfigList feeConfig,YeePayProductInfo productInfo){
        //1 百分比 2 固定值 3 百分比+固定值
        switch (feeConfig.getDefaultFeeConfigValue().getFeeType()){
            case 1:
                productInfo.setRateType("SINGLE_PERCENT");
                productInfo.setPercentRate(feeConfig.getDefaultFeeConfigValue().getRateBase().toString());
                break;
            case 2:
                productInfo.setRateType("SINGLE_FIXED");
                productInfo.setFixedRate(feeConfig.getDefaultFeeConfigValue().getFixedRate().toString());
                break;
            case 3:
                productInfo.setRateType("FIXED_MIX_PERCENT");
                productInfo.setPercentRate(feeConfig.getDefaultFeeConfigValue().getRateBase().toString());
                productInfo.setFixedRate(feeConfig.getDefaultFeeConfigValue().getFixedRate().toString());
                break;

        }

        // 阶梯费率
        // if(feeConfig.getStepFeeType() == 1){
        //     List<YeePayProductInfo.LadderFee> ladderFees = YeePayProductInfo.formatLadderFeeList(feeConfig.getStepFeeConfigs());
        //     productInfo.setLadderFeeList(ladderFees);
        // }

        // 保底
        // if(feeConfig.getSeniorFeeType() == 1){
        //     productInfo.setMinRate(feeConfig.getSeniorFeeConfigValue().getProviderMinFee().toString());
        // }

    }

    /**
     * 获取支付宝产品编码
     * @param payWayDO
     * @return
     */
    public String getAliProductCode(PayWayDO payWayDO){
        String productCode = null;
        PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.fromByType(payWayDO.getSubType());
        PayEnums.SCENE_TYPE sceneType = PayEnums.SCENE_TYPE.from(payWayDO.getSceneType());
        switch (sceneType) {
            case ONLINE:
                switch (scenePayType) {
                    case JSAPI:
                        // productCode = "ALIPAY_LIFE_ALIPAY_ONLINE";
                        break;
                    case SCAN:
                        productCode = "MERCHANT_SCAN_ALIPAY_ONLINE";
                        break;
                    case APP:
                        // productCode = "SDK_PAY_ALIPAY_ONLINE";
                        break;
                }
                break;
            case OFFLINE:
                switch (scenePayType) {
                    case MINI_APP:
                        productCode = "MINI_PROGRAM_ALIPAY_OFFLINE";
                        break;
                    case JSAPI:
                        productCode = "ALIPAY_LIFE_ALIPAY_OFFLINE";
                        break;
                    case QR:
                        productCode = "USER_SCAN_ALIPAY_OFFLINE";
                        break;
                    case SCAN:
                        productCode = "MERCHANT_SCAN_ALIPAY_OFFLINE";
                        break;
                    case H5:
                        // productCode = "H5_PAY_M_ALIPAY_OFFLINE";
                        break;
                }
                break;
        }
        return productCode;
    }

    /**
     * 获取微信产品编码
     * @param payWayDO
     * @return
     */
    public String getWxProductCode(PayWayDO payWayDO){
        String productCode = null;
        PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.fromByType(payWayDO.getSubType());
        PayEnums.SCENE_TYPE sceneType = PayEnums.SCENE_TYPE.from(payWayDO.getSceneType());
        switch (sceneType) {
            case ONLINE:
                switch (scenePayType) {
                    case MINI_APP:
                        // 非面对面
                        // productCode = "MINI_PROGRAM_WECHAT_ONLINE";
                        break;
                    case JSAPI:
                        // 面对面#非面对面
                        productCode = "WECHAT_OFFIACCOUNT_WECHAT_ONLINE";
                        break;
                    case SCAN:
                        // 面对面
                        productCode = "MERCHANT_SCAN_WECHAT_ONLINE";
                        break;
                    case APP:
                        // 非面对面
                        // productCode = "SDK_PAY_WECHAT_ONLINE";
                        break;
                }
                break;
            case OFFLINE:
                switch (scenePayType) {
                    case MINI_APP:
                        // 面对面#非面对面
                        productCode = "MINI_PROGRAM_WECHAT_OFFLINE";
                        break;
                    case JSAPI:
                        // 面对面#非面对面
                        productCode = "WECHAT_OFFIACCOUNT_WECHAT_OFFLINE";
                        break;
                    case QR:
                        // 面对面#非面对面
                        productCode = "USER_SCAN_WECHAT_OFFLINE";
                        break;
                    case SCAN:
                        // 面对面
                        productCode = "MERCHANT_SCAN_WECHAT_OFFLINE";
                        break;
                    case H5:
                        // 非面对面
                        // productCode = "H5_PAY_M_WECHAT_OFFLINE";
                        break;
                }
                break;
        }
        return productCode;
    }

    public CommonResult<YeePayConfig> yeePayConfig(ProviderChannelConfigDO providerChannelConfigDO, boolean test) {
        String paramsConfig = providerChannelConfigDO.getParamsConfig();
        if (StringUtils.isEmpty(paramsConfig)) {
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS);
        }
        // 配置转换
        YeePayConfig yeePayConfig = null;
        try {
            yeePayConfig = JsonUtils.parseObject(paramsConfig, YeePayConfig.class);
            return CommonResult.success(yeePayConfig);
        }
        catch (Exception e) {
            String format = String.format(PayResultCode.PAY_CHANNEL_CONFIG_ERROR.getMsg(), "易宝");
            return CommonResult.error(PayResultCode.PAY_CHANNEL_CONFIG_NOT_EXITS.getCode(), format);
        }
    }


    /**
     * 获取受益人信息
     * @param uboInfoList
     * @param yeePayConfig
     * @return
     */
    public JSONArray getUnoArray(List<MerchantAccessCertInfoDO> uboInfoList,YeePayConfig yeePayConfig) {
        JSONArray JSONArray = new JSONArray();
        try{
            if(CollUtil.isEmpty(uboInfoList)){
                return null;
            }
            for(MerchantAccessCertInfoDO uboInfo:uboInfoList){
                com.alibaba.fastjson.JSONObject dto = new com.alibaba.fastjson.JSONObject();
                dto.put("type",uboInfo.getOtherValue());
                // // 受益人证件类型
                dto.put("licenceType", certType(uboInfo.getCertType()));
                // 受益人名称
                dto.put("name",  uboInfo.getName());
                // 证件号码
                dto.put("licenceNo",  uboInfo.getCertNo());
                // 证件正面照片
                dto.put("licenceFrontUrl", getUploadMerQualUrl(uboInfo.getCertFrontUrl(),yeePayConfig));
                // 证件反面照片
                dto.put("licenceBackUrl", getUploadMerQualUrl(uboInfo.getCertBackUrl(),yeePayConfig));
                // 受益人证件地址
                dto.put("address",  uboInfo.getAddress());
                // 受益人证件有效期开始时间
                dto.put("startDate", uboInfo.getCertBeginDate());
                if(uboInfo.getCertValidityType() == 1){
                    dto.put("validityType", "LONG_TERM");
                }else{
                    // 受益人证件有效期结束时间
                    dto.put("expired", uboInfo.getCertEndDate());
                }
                JSONArray.add(dto);
            }

        }catch (Exception e){
            throw new RuntimeException("yeepay getUnoArray 异常", e);
        }
        return JSONArray;
    }

    /**
     * 获取微信受益人信息
     * @param uboInfoList
     * @param yeePayConfig
     * @return
     */
    public JSONArray getWxUnoArray(List<MerchantAccessCertInfoDO> uboInfoList,YeePayConfig yeePayConfig) {
        JSONArray JSONArray = new JSONArray();
        try{
            if(CollUtil.isEmpty(uboInfoList)){
                return null;
            }
            for(MerchantAccessCertInfoDO uboInfo:uboInfoList){
                com.alibaba.fastjson.JSONObject dto = new com.alibaba.fastjson.JSONObject();
                // 受益人证件类型
                dto.put("uboIdDocType", WxPayCommonParamsHandle.certType(uboInfo.getCertType()));
                // 受益人名称
                dto.put("uboIdDocName",  uboInfo.getName());
                // 证件号码
                dto.put("uboIdDocNumber",  uboInfo.getCertNo());
                // 证件正面照片
                dto.put("uboIdDocCopy", getUploadMerQualUrl(uboInfo.getCertFrontUrl(),yeePayConfig));
                // 证件反面照片
                dto.put("uboIdDocCopyBack", getUploadMerQualUrl(uboInfo.getCertBackUrl(),yeePayConfig));
                // 受益人证件地址
                dto.put("uboIdDocAddress",  uboInfo.getAddress());
                // 受益人证件有效期
                if(uboInfo.getCertValidityType() == 1){
                    dto.put("uboIdValidDate", CollUtil.newArrayList(uboInfo.getCertBeginDate(),"forever"));
                }else{
                    dto.put("uboIdValidDate", CollUtil.newArrayList(uboInfo.getCertBeginDate(),uboInfo.getCertEndDate()));
                }
                JSONArray.add(dto);
            }

        }catch (Exception e){
            throw new RuntimeException("yeepay getUnoArray 异常", e);
        }
        return JSONArray;
    }


    /**
     * 获取支付宝受益人信息
     * @param uboInfoList
     * @param yeePayConfig
     * @return
     */
    public JSONArray getAliUnoArray(List<MerchantAccessCertInfoDO> uboInfoList,YeePayConfig yeePayConfig) {
        JSONArray JSONArray = new JSONArray();
        try{
            if(CollUtil.isEmpty(uboInfoList)){
                return null;
            }
            for(MerchantAccessCertInfoDO uboInfo:uboInfoList){
                com.alibaba.fastjson.JSONObject dto = new com.alibaba.fastjson.JSONObject();
                // 受益人证件类型
                dto.put("uboIdDocType", WxPayCommonParamsHandle.certType(uboInfo.getCertType()));
                // 受益人名称
                dto.put("uboIdDocName",  uboInfo.getName());
                // 证件号码
                dto.put("uboIdDocNumber",  uboInfo.getCertNo());
                // 证件正面照片
                dto.put("uboIdDocCopy", getUploadMerQualUrl(uboInfo.getCertFrontUrl(),yeePayConfig));
                // 证件反面照片
                dto.put("uboIdDocCopyBack", getUploadMerQualUrl(uboInfo.getCertBackUrl(),yeePayConfig));
                // 受益人证件地址
                dto.put("uboIdDocAddress",  uboInfo.getAddress());
                dto.put("uboPeriodBeginTime",  uboInfo.getCertBeginDate());
                // 受益人证件有效期
                if(uboInfo.getCertValidityType() == 1){
                    dto.put("uboPeriodEndTime", "forever");
                }else{
                    dto.put("uboPeriodEndTime", uboInfo.getCertEndDate());
                }
                JSONArray.add(dto);
            }

        }catch (Exception e){
            throw new RuntimeException("yeepay getUnoArray 异常", e);
        }
        return JSONArray;
    }


    /**
     * 获取入网商户业务角色
     * @param platformNo          平台商户号，读服务商配置
     * @param merchantAccessType  商户入网类型 等于1就是分账接收方
     * @return
     */
    public String getBusinessRole(String platformNo,Integer merchantAccessType){
        // 商户入网类型 0=收单子商户，1=分账子商户，默认为收单子商户
        if(merchantAccessType != null){
            if(merchantAccessType == 0){
                if(StrUtil.isEmpty(platformNo)){
                    return "ORDINARY_MERCHANT";
                }else{
                    return "SETTLED_MERCHANT";
                }
            }else{
                return "SHARE_MERCHANT";
            }
        }else{
            if(StrUtil.isEmpty(platformNo)){
                return "ORDINARY_MERCHANT";
            }else{
                return "SETTLED_MERCHANT";
            }
        }
    }


    public String licenseType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1：营业执照
        // 2：营业执照(多证合一)
        // 3：事业单位法人证书
        // 4：社会团体法人登记证书
        // 5：民办非企业单位登记证书
        // 6：基金会法人登记证书
        // 7：宗教活动场所登记证
        // 8：其他证书/批文/证明
        // 9：执业许可证/执业证
        // 10：基层群众性自治组织特别法人统一社会信用代码证
        // 11：农村集体经济组织登记证
        // 12：业主委员会备案证明

        // CERTIFICATE_TYPE_2388 事业单位法人证书
        // CERTIFICATE_TYPE_2389 统一社会信用代码证书
        // CERTIFICATE_TYPE_2390 有偿服务许可证（军队医院适用）
        // CERTIFICATE_TYPE_2391 医疗机构执业许可证（军队医院适用）
        // CERTIFICATE_TYPE_2392 企业营业执照（挂靠企业的党组织适用）
        // CERTIFICATE_TYPE_2393 组织机构代码证（政府机关适用）
        // CERTIFICATE_TYPE_2394 社会团体法人登记证书
        // CERTIFICATE_TYPE_2395 民办非企业单位登记证书
        // CERTIFICATE_TYPE_2396 基金会法人登记证书
        // CERTIFICATE_TYPE_2397 慈善组织公开募捐资格证书
        // CERTIFICATE_TYPE_2398 农民专业合作社法人营业执照
        // CERTIFICATE_TYPE_2399 宗教活动场所登记证
        // CERTIFICATE_TYPE_2400 其他证书/批文/证明
        switch (code) {
            case "1":
            case "2":
            case "10":
                return "CERTIFICATE_TYPE_2389";
            case "3":
                return "CERTIFICATE_TYPE_2388";
            case "4":
                return "CERTIFICATE_TYPE_2394";
            case "5":
                return "CERTIFICATE_TYPE_2395";
            case "6":
                return "CERTIFICATE_TYPE_2396";
            case "7":
                return "CERTIFICATE_TYPE_2399";
            case "8":
            case "9":
            case "12":
                return "CERTIFICATE_TYPE_2400";
            case "11":
                return "CERTIFICATE_TYPE_2398";
            default:
                return null;
        }
    }

    public String certType(String code) {
        if (!StringUtils.hasText(code)) {
            return null;
        }
        // 营业执照类型：
        // 1:身份证
        // 2:护照
        // 3:军官证
        // 4:士兵证
        // 5:回乡证
        // 6:户口本
        // 7:外国护照
        // 8:其他
        // 9:暂住证
        // 10:警官证
        // 11:文职干部证
        // 12:港澳台同胞通行证
        // 13:外国人居留证
        // 14:台胞证
        // 15:港澳台居住证
        // 16：营业执照 （只有部分场景才会用到 如 受益人和股东）


        /**
         ID_CARD: 身份证
         PASSPORT: 护照
         HM_VISITORPASS: 港澳居民往来内地通行证
         TAIWAN: 台胞证
         FPRP: 外国人永久居留身份证
         SOLDIER: 士兵证
         OFFICERS: 军官证
         */
        switch (code) {
            case "1":
                return "ID_CARD";
            case "2":
                return "PASSPORT";
            case "12":
                return "HM_VISITORPASS";
            case "14":
                return "TAIWAN";
            case "13":
                return "FPRP";
            case "4":
                return "SOLDIER";
            case "10":
                return "OFFICERS";
            default:
                return null;
        }
    }

    /**
     * 易宝进件主体类型
     * INDIVIDUAL : 个体工商户
     * ENTERPRISE : 企业
     * INSTITUTION: 事业单位
     * COMMUNITY:   社会团体
     * PEOPLE_RUN_NON_ENTERPRISE :民办非企业
     *
     * 系统主体类型
     * 1：政府机构
     * 2：国营企业
     * 3：私营企业
     * 4：外资企业
     * 5：个体工商户
     * 6：其它组织
     * 7：事业单位
     * 8：业主委员会；
     */
    public  String companyType(Integer type) {
        String companyType = null;
        switch (type){
            case 1:
                companyType = "INSTITUTION";
                break;
            case 2:
            case 3:
            case 4:
                companyType = "ENTERPRISE";
                break;
            case 5:
                companyType = "INDIVIDUAL";
                break;
            case 6:
            case 8:
                companyType = "PEOPLE_RUN_NON_ENTERPRISE";
                break;
            case 7:
                companyType = "INSTITUTION";
                break;
        }

        return companyType;
    }


    /**
     * 过去指定场景类型的数据
     * @param sceneList
     * @param senceType
     * @return
     */
    public  MerchantAccessScene getMerchantAccessSceneValue(List<MerchantAccessScene> sceneList, Integer senceType){
        if(CollUtil.isNotEmpty(sceneList)){
            for(MerchantAccessScene accessScene:sceneList){
                if(accessScene.getType() == senceType){
                    return accessScene;
                }
            }

        }
        return null;
    }

    /**
     * 0：对公账户 1：对私法人账户 2：对私非法人账户
     * @param type
     * @return
     */
    public String getBankAccountType(Integer type){
        String bankAccountType = null;
        if(type == null){
            return bankAccountType;
        }
        switch (type){
            case 0:
                bankAccountType = "ENTERPRISE_ACCOUNT";
                break;
            default:
                bankAccountType = "DEBIT_CARD";
                break;
        }
        return bankAccountType;
    }

    /**
     * 易宝上传图片获取merQualUrl
     * @param filePath   本地路劲/https
     * @param yeePayConfig
     * @return
     */
    public String getUploadMerQualUrl(String filePath, YeePayConfig yeePayConfig) {

        try {

            File file = null;
            if(HttpUtil.isHttp(filePath)  || HttpUtil.isHttps(filePath) ){
                // 创建临时文件
                file =  FileUtil.createTempFile("."+ ImageUtils.getFileExtension(filePath),true);
                // 文件流copy到临时文件
                HttpUtil.downloadFile(filePath,file);
            }else{
                file = FileUtil.newFile(filePath);
            }

            if(FileUtil.isEmpty(file)){
                log.error("易宝 Upload 上传文件格式异常 ");
                throw new RuntimeException("易宝 Upload 上传文件格式异常");
            }

            YopClient yopClient = YopClientBuilder.builder().withEndpoint("https://openapi.yeepay.com/yop-center").build();
            YopRequest request = new YopRequest("/yos/v1.0/sys/merchant/qual/upload", "POST");
            String appKey = yeePayConfig.getAppId();
            request.getRequestConfig().setAppKey(appKey);
            request.getRequestConfig().setSecurityReq("YOP-RSA2048-SHA256");
            request.getRequestConfig().setCredentials(new YopPKICredentials(
                    appKey, new PKICredentialsItem(getPrivateKey(
                    yeePayConfig.getPrivateKey(),
                    CertTypeEnum.RSA2048),
                    CertTypeEnum.RSA2048)));

            request.addMultiPartFile("merQual", FileUtil.getInputStream(file));
            YopResponse response = yopClient.request(request);

            log.info("易宝 Upload 上传文件 filePath :{}, 配置 :{}, 返回参数 :{}",filePath, JSONUtil.toJsonStr(yeePayConfig),JSONUtil.toJsonStr(response));
            if(StrUtil.isNotEmpty(response.getStringResult())){
                      JSONObject respBody = JSONUtil.parseObj(response.getResult());
                      Object merQualUrl = respBody.get("merQualUrl");
                      if(merQualUrl != null){
                          return merQualUrl.toString();
                      }
            }else{
                throw new RuntimeException("易宝 Upload 上传文件异常 : "+filePath+" , "+ JSONUtil.toJsonStr(response));
            }
        } catch (Exception e) {
            log.error("易宝 Upload 上传文件异常", e);
            throw new RuntimeException("易宝 Upload 上传文件异常", e);
        }
        return null;
    }


    public static PrivateKey getPrivateKey(String priKey, CertTypeEnum certType) {
        final YopCertConfig yopCertConfig = new YopCertConfig();
        yopCertConfig.setCertType(certType);
        yopCertConfig.setValue(priKey);
        yopCertConfig.setStoreType(CertStoreType.STRING);
        return (PrivateKey) YopCertParserFactory.getCertParser(YopCertCategory.PRIVATE, certType).parse(yopCertConfig);
    }


    /**
     * 获取支付方式
     * @param payWayDO
     * @return
     */
    public String getPayWay(PayWayDO payWayDO){
        String payway = null;
        // 支付渠道枚举
        PayEnums.SCENE_PAY_TYPE scenePayType = PayEnums.SCENE_PAY_TYPE.from(payWayDO.getSubType());
        // 支付方式枚举
        PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
        switch(scenePayType){
              case QR:
                  payway = "USER_SCAN";
                  break;
              case JSAPI:
                  switch (payType){
                      case WECHAT:
                          payway = "WECHAT_OFFIACCOUNT";
                          break;
                      case ALIPAY:
                          payway = "ALIPAY_LIFE";
                          break;
                      case UNION_APY:
                          payway = "JS_PAY";
                          break;
                  }
                  break;
              case MINI_APP:
                  payway = "MINI_PROGRAM";
                  break;
            case H5:
                payway = "H5_PAY";
                break;
            case APP:
                payway = "SDK_PAY";
                break;
            case SCAN:
                payway = "MERCHANT_SCAN";
                break;
        }

        return payway;
    }

    /**
     * 获取渠道类型
     * @param payWayDO
     * @return
     */
    public String getPayChannel(PayWayDO payWayDO){
        String  payChannel = null;
        PayEnums.PAY_TYPE payType = PayEnums.PAY_TYPE.fromByCode(payWayDO.getType());
        switch(payType){
            case WECHAT:
                payChannel = "WECHAT";
                break;
            case ALIPAY:
                payChannel = "ALIPAY";
                break;
            case UNION_APY:
                payChannel = "UNIONPAY";
                break;
            case DIGITAL:
                payChannel = "DCEP";
                break;
        }
        return payChannel;
    }


    /**
     * 获取支付场景
     * @param payWayDO
     * @return
     */
    public String getPayScene(PayWayDO payWayDO){
        String scene = null;
        PayEnums.SCENE_TYPE sceneType = PayEnums.SCENE_TYPE.from(payWayDO.getSceneType());
        switch (sceneType){
            case OFFLINE:
                scene = "OFFLINE";
                break;
            case ONLINE:
                scene = "ONLINE";
                break;
        }
        return scene;
    }

    /**
     * 获取易宝分账明细单号
     * @param ledgerNo     分账接收方编号
     * @param divideDetail 分账详情
     * @param type 取值类型 true:取类型 false:明细单号
     * @return
     */
    public String getDivideDetailNo(String ledgerNo,String divideDetail,boolean type){
        if(StrUtil.isEmpty(divideDetail)){
            return null;
        }
        List<YeePayDivideDetailResp> detailRespList = JSONUtil.toList(divideDetail,YeePayDivideDetailResp.class);
        if(CollUtil.isNotEmpty(detailRespList)){
            for(YeePayDivideDetailResp detailResp:detailRespList){
                if(detailResp.getLedgerNo().equals(ledgerNo)){
                    if(type){
                        return detailResp.getLedgerType();
                    }else{
                        return detailResp.getDivideDetailNo();
                    }

                }
            }
        }
        return null;
    }

    public PayOrderDO queryPayOrder(String orderId){
        return payOrderService.queryPayOrderNoCache(orderId);
    }

    /**
     * 时间戳转DateTime
     * @param timestamp
     * @return
     */
    public DateTime formatTimestamp(long timestamp){
        String pattern = DatePattern.NORM_DATETIME_PATTERN;
        String dateStr = DateUtils.dateToString(timestamp, pattern);
        return DateTime.parse(dateStr,DateTimeFormat.forPattern(pattern));
    }



    public static void main(String[] args) {
        YeePayConfig yeePayConfig = new YeePayConfig();
        yeePayConfig.setAppId("app_10089798423");
        yeePayConfig.setMchId("10089798423");
        yeePayConfig.setPrivateKey("MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCbpEqTMdaC6cciHsTMv+8eeUAFmoLt97D4r+c6X1Yz2FPjGrlcz5qqr1L7ZL9EL8/bZnb4C1e17Y3QOnW3LKO1xNIO08kXdbeSfWbY08ssGPSbTE28OFMn92Zl80ldQeppKTEcrxwkwQtuP2oplyn+LapjEc0FYDetvc8LeSBxd9lS+EVyUa+Rx3a14vi65ELw61tOzbUi4bEseUJMRjhfkATtRrHM6jtKoSe9b3PVKdnUE+XH2ZYG+4e4eOOcw2o9AdBX/yU4r9Z8t2pEiLFF2RT6h8uFtb6sS9gdB1chU4mdo6pdB037io8FwNKA3mFYhDNau08BYAeHSEvQNxKhAgMBAAECgf9s03NReIeFAfE66kiw4YNQy3b4dBEYUxhqypPjPMYJejktkoIJYx/CONTM8qTKCKRNxFdrGIM7sd52ummUqqHNdtFpjKwOu0CgLQ68jVqCevCNpcy0zq1WRKZUosepbW16GlM8uzPyfwh/DdgtPIUgNM3ud4PjPmOwGAes/gSxUQObFvu9eEaLkgb0TwRXZYd1N02M7xkPXUcLG4Ls/NV0xZ+zPxNl7JXVnFf0gp6O0CRyuRnwLRjwEBbKb5rbkgG47b9/44o4ma3HVyqZhhA7WrTlY38xeW4lVVqsACJ1LJl2uioQnSedOpH8QIsANZV7F8hWgqgkncEUFwsE7xECgYEA2Dh2gN24SPEO4qsiBkHmeGJJzwVKGeMNJxpSDYJ0X03k11Fwno+mY5BUPFSH+5deZvs+trte4nu519w0ltme678smfrYbSDIyg7w630eLgz8w+hFe1xo496cnQ2mIIwp2fySXNWLJHUyWeGR/nCRl27496pJM9yLo5HxbkHx16UCgYEAuEaxjQwVzZQR3DrmLC4H/NI2oKS0vCbbNRudHduyumacwxngaCCpaIUam/D6q6FJu2l43gOAXwBNFwq2JbpPl9Df+x1QIzLgCnTmCZc7zIKhxI6MHrQRU3sSoJgrJMPqrUlcNBVjiQUUudc1OT5raojBM+wYA1Oie0cU52kefk0CgYBZ2czU7E5CcXoAE6GF/Cir6hxF3SrX6xRyJWvnlUiKujHYkE0+du9r/HQkxfPkRxjBrrJ2+RILB+NIoodwEGsMCFueeTEq2C7YWLEhCtNZy6fWOVV2WAZ2evGWCi/44oYZwe2IimzR76nG1Af5NgoqZcEsGiVlWcblaCZt7RV0yQKBgQCcwdZsC+nINbtzws7mqkm1MgWyZioxHETBSro/GhNSKdQUy8BwE8jI1uGp4jb7JXsZaEGfaw8awaDShxQnx/PJS7AdZ/Qx3Sdk/chqRDJkaIPANxrPS5KplzpjTs70uYy62HsM+1zuxFm7NW1bQtQRjj/8MUzEF7NSd0c7C9sayQKBgQCyKawGfP/NeLdfrOVJ8QYI02AjFkGQWfPGT58FRHRiGdzcqzK9h5ZhRyMNr1qRZ09ZLgcDEVCCOq58hdC8YY8wUyWE5/4+TYgfKRt4J2S8AXQ5roAVXcn7e+CFQarqGrMRtoVR6uTPH0BvGQNNd+O0w6Zfz6zDVn4cF1ir+dbStA==");
        yeePayConfig.setPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6p0XWjscY+gsyqKRhw9MeLsEmhFdBRhT2emOck/F1Omw38ZWhJxh9kDfs5HzFJMrVozgU+SJFDONxs8UB0wMILKRmqfLcfClG9MyCNuJkkfm0HFQv1hRGdOvZPXj3Bckuwa7FrEXBRYUhK7vJ40afumspthmse6bs6mZxNn/mALZ2X07uznOrrc2rk41Y2HftduxZw6T4EmtWuN2x4CZ8gwSyPAW5ZzZJLQ6tZDojBK4GZTAGhnn3bg5bBsBlw2+FLkCQBuDsJVsFPiGh/b6K/+zGTvWyUcu+LUj2MejYQELDO3i2vQXVDk7lVi2/TcUYefvIcssnzsfCfjaorxsuwIDAQAB");


        YopClient yopClient = YopClientBuilder.builder().build();

        // // 请求级配置
        // YopRequestConfig requestConfig = new YopRequestConfig();
        // requestConfig.setSecurityReq(securityReq).setAppKey(appId);
        // YopRequest request = new YopRequest("/rest/v1.0/file/upload", "POST", requestConfig);
        //
        // YopResponse response = yopClient.request(request);





    }


}
